//
// Created by 32827 on 2023/11/16.
//
#include "yzf_clock.h"

YZF_RESULT yzf_clock_PLL_ready(){
    if(RCC->CR&RCC_CR_PLLRDY){
        return YZF_OK;
    }else{
        return YZF_CLOCK_NOT_READY;
    }
}
YZF_RESULT yzf_clock_HSE_ready(){
    if(RCC->CR&RCC_CR_HSERDY){
        return YZF_OK;
    }else{
        return YZF_CLOCK_NOT_READY;
    }
}
YZF_RESULT yzf_clock_HSI_ready(){
    if (RCC->CR&RCC_CR_HSIRDY){
        return YZF_OK;
    }else{
        return YZF_CLOCK_NOT_READY;
    }
}
YZF_RESULT yzf_clock_PLL_ON(){
    RCC->CR|=RCC_CR_PLLON;
    while(yzf_clock_PLL_ready() != YZF_OK);
    return YZF_OK;
}
YZF_RESULT yzf_clock_PLL_OFF(){
    RCC->CR&=~RCC_CR_PLLON;
    return YZF_OK;
}
YZF_RESULT yzf_clock_HSE_ON(){
    RCC->CR|=RCC_CR_HSEON;
    while(yzf_clock_HSE_ready() != YZF_OK);
    return YZF_OK;
}
YZF_RESULT yzf_clock_HSE_OFF(){
    RCC->CR&=~RCC_CR_HSEON;
    return YZF_OK;
}
YZF_RESULT yzf_clock_HSI_ON(){
    RCC->CR|=RCC_CR_HSION;
    while(yzf_clock_HSI_ready() != YZF_OK);
    return YZF_OK;
}
YZF_RESULT yzf_clock_HSI_OFF(){
    RCC->CR&=~RCC_CR_HSION;
    return YZF_OK;
}
/**
 * PLL倍频系数 2-16 倍
 * */
YZF_RESULT yzf_clock_PLL_MUL(uint8_t mul){
    if(!(mul>=2&&mul<=16)){
        return YZF_NOT_FOUND;
    }
    //TODO: Need to suit
//    RCC->CFGR&=~RCC_CFGR_PLLMULL;
//    RCC->CFGR|=(mul-2)<<RCC_CFGR_PLLMULL_Pos;
//    return YZF_OK;
    return YZF_ERROR;
}
/**
 * [SYSCLK]外设总线分频 可取1 2 4 8 16 32 64 128 256 512
 * */
YZF_RESULT yzf_clock_AHB_DIV(uint16_t div){
    switch (div) {
        case 1:
            div=0b0000;
            break;
        case 2:
            div=0b1000;
            break;
        case 4:
            div=0b1001;
            break;
        case 8:
            div=0b1010;
            break;
        case 16:
            div=0b1011;
            break;
        case 64:
            div=0b1100;
            break;
        case 128:
            div=0b1101;
            break;
        case 256:
            div=0b1110;
            break;
        case 512:
            div=0b1111;
            break;
        default:
            return YZF_NOT_FOUND;
    }
    RCC->CFGR&=~RCC_CFGR_HPRE;
    RCC->CFGR|=div<<RCC_CFGR_HPRE_Pos;
    return YZF_OK;
}
/**
 * [AHB]外设总线-分线1 可取1 2 4 8 16 最高可设置为36MHz
 * */
YZF_RESULT yzf_clock_APB1_DIV(uint8_t div){
    switch (div) {
        case 1:
            div=0b000;
            break;
        case 2:
            div=0b100;
            break;
        case 4:
            div=0b101;
            break;
        case 8:
            div=0b110;
            break;
        case 16:
            div=0b111;
            break;
        default:
            return YZF_NOT_FOUND;
    }
    RCC->CFGR&=~RCC_CFGR_PPRE1;
    RCC->CFGR|=div<<RCC_CFGR_PPRE1_Pos;
    return YZF_OK;
}
/**
 * [AHB]外设总线-分线2 可取1 2 4 8 16 最高可设置为72MHz
 * */
YZF_RESULT yzf_clock_APB2_DIV(uint8_t div){
    switch (div) {
        case 1:
            div = 0b000;
            break;
        case 2:
            div = 0b100;
            break;
        case 4:
            div = 0b101;
            break;
        case 8:
            div = 0b110;
            break;
        case 16:
            div = 0b111;
            break;
        default:
            return YZF_NOT_FOUND;
    }
    RCC->CFGR &= ~RCC_CFGR_PPRE2;
    RCC->CFGR |= div << RCC_CFGR_PPRE2_Pos;
    return YZF_OK;
}
/**
 * 设置PLL时钟源 可选 HSI_2(HSI二分频) HSE HSE_2(HSE二分频)
 * */
YZF_RESULT yzf_clock_PLL_set_source(YZF_CLOCK_SOURCE source){
//    switch (source) {
//        case hsi_2:
//            RCC->CFGR&=~(0b1UL<<RCC_CFGR_PLLSRC_Pos);
//            break;
//        case hse_2:
//            RCC->CFGR|=0b1<<RCC_CFGR_PLLXTPRE_Pos;
//            break;
//        case hse:
//            RCC->CFGR|=0b1<<RCC_CFGR_PLLSRC_Pos;
//            break;
//        default:
//            return YZF_NOT_FOUND;
//    }
//    return YZF_OK;
    //TODO: Need to suit
    return YZF_ERROR;
}
/**
 * 设置SYS时钟源 可选 HSI HSE PLL
 * */
YZF_RESULT yzf_clock_SYS_set_source(YZF_CLOCK_SOURCE source){
    switch (source) {
        case hsi:
            RCC->CFGR&=~(0b11UL<<RCC_CFGR_SW_Pos);
            break;
        case hse:
            RCC->CFGR|=0b01<<RCC_CFGR_SW_Pos;
            break;
        case pll:
            RCC->CFGR|=0b10<<RCC_CFGR_SW_Pos;
            break;
        default:
            return YZF_NOT_FOUND;
    }
    return YZF_OK;
}